/**
 * 
 */
package com.dems.core.util;

import com.dems.core.log.TraceIdContext;

import java.util.concurrent.*;

/**
 * @author tinyylh
 * 
 */
public class ThreadPool {

	private ThreadPoolExecutor threadPool;
	private ScheduledThreadPoolExecutor shceduledPool;

	private ThreadPool() {
		int cpuNum = Runtime.getRuntime().availableProcessors();
		cpuNum -= 1;
		cpuNum = cpuNum > 0 ? cpuNum : 1;

		threadPool = new ThreadPoolExecutor(cpuNum*2, cpuNum*20, 3, TimeUnit.SECONDS, new SynchronousQueue<>(),
				new ThreadPoolExecutor.CallerRunsPolicy());
		shceduledPool = new ScheduledThreadPoolExecutor(1, new ThreadPoolExecutor.AbortPolicy());
	}

	private static ThreadPool instance = null;

	public static ThreadPool getInstance() {
		if (instance == null) {
			instance = new ThreadPool();
		}
		return instance;
	}

	public void execute(Runnable runnable) {
		threadPool.execute(ThreadMdcUtil.wrap(runnable, TraceIdContext.getContextMap()));
	}

	public void execute(Runnable runnable, long delay, TimeUnit timeUnit) {
		shceduledPool.schedule(ThreadMdcUtil.wrap(runnable, TraceIdContext.getContextMap()), delay, timeUnit);
	}

	/**
	 * 获取异步执行结果
	 * @param task
	 * @param <T>
	 * @return
	 */
	public <T> Future<T> submit(Callable<T> task) {
		return threadPool.submit(ThreadMdcUtil.wrap(task, TraceIdContext.getContextMap()));
	}

	public void shutDown() {
		threadPool.shutdown();
		shceduledPool.shutdown();
	}

	public ThreadPoolExecutor getThreadPool() {
		return threadPool;
	}


	public static <T> CompletionService<T> getCompletionService() {
		return new ExecutorCompletionService<>(getInstance().getThreadPool());
	}

}
